package com.tansun.easycare.rule.rulegroup.web;

import java.io.File;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.tansun.easycare.rule.common.enums.RuleModelTypeFileEnum;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContextException;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.tansun.easycare.core.utils.ResponseTable;
import com.tansun.easycare.rule.common.DataCache;
import com.tansun.easycare.rule.common.JsonMessage;
import com.tansun.easycare.rule.common.ResMessage;
import com.tansun.easycare.rule.common.RuleBaseController;
import com.tansun.easycare.rule.common.model.ResponseVO;
import com.tansun.easycare.rule.common.service.DataBomService;
import com.tansun.easycare.rule.common.service.RuleGeneralService;
import com.tansun.easycare.rule.common.web.model.ProjectInfo;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.ruleexcute.model.RuleExecuteVO;
import com.tansun.easycare.rule.rulegroup.entity.RuleGroup;
import com.tansun.easycare.rule.rulegroup.entity.RuleGroupRef;
import com.tansun.easycare.rule.rulegroup.model.RuleEditEntity;
import com.tansun.easycare.rule.rulegroup.model.RuleGroupInfo;
import com.tansun.easycare.rule.rulegroup.model.RuleRefVOPage;
import com.tansun.easycare.rule.rulegroup.model.RuleSetVO;
import com.tansun.easycare.rule.rulegroup.service.RuleGroupRefService;
import com.tansun.easycare.rule.rulegroup.service.RuleGroupService;
import com.tansun.easycare.rule.rulemange.entity.RuleManage;
import com.tansun.easycare.rule.rulemange.model.RuleManageVO;
import com.tansun.easycare.rule.rulemange.service.RuleManageService;
import com.tansun.easycare.rule.ruleversion.entity.RuleVersioninfo;
import com.tansun.easycare.rule.ruleversion.service.RuleVersioninfoService;
import com.tansun.rule.common.RuleModelTypeEnum;
import com.tansun.rule.utils.LoggerManager;
import com.tansun.rule.utils.MClass;
import com.tansun.rule.utils.MField;

@RestController
@RequestMapping(value = "/ruleProj/generalRule")
public class GeneralRuleController extends RuleBaseController {

    @Autowired
    private RuleManageService ruleManageService;

    @Autowired
    private RuleGroupService ruleGroupService;

    @Autowired
    private RuleGroupRefService ruleGrouprefService;

    @Autowired
    private RuleGeneralService ruleGeneralService;
    
    @Autowired
    private DataBomService dataBomService;
    
    @Autowired
    private RuleVersioninfoService ruleVersioninfoService;

//    @Autowired
//    private RuleGroupUtils ruleGroupUtils;
    
    /**
     * 打开规则集列表
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param code     普通规则编码
     * @param type     规则集类别 普通，一般，政策
     * @param map      ModelMap
     * @return JSP路径
     */
    @RequestMapping("index")
    public ResponseTable<RuleManageVO> index(@RequestBody RuleManageVO param) throws Exception {
        PageInfo<RuleManageVO> pageInfo = this.ruleManageService.findRuleManageVO(param.getPage(), param);
        ResponseTable<RuleManageVO>  resVo  = new  ResponseTable<RuleManageVO>(pageInfo);
        return resVo;
    }

    /**
     * 规则编辑页面
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @return JSP路径
     */
    @RequestMapping("getRuleDetail")
    public ResponseVO getRuleDetail(@RequestBody ProjectInfo projectInfo) throws Exception {
    	ResponseVO responseVO = new ResponseVO();
    	try {
        	RuleEditEntity ruleEditEntity = new RuleEditEntity();
        	RuleManage rulemanage = this.ruleManageService.get(projectInfo.getManageId());
        	ruleEditEntity.setRuleManage(rulemanage);
        	RuleGroup condition = new RuleGroup();
        	condition.setManageId(rulemanage.getId());
        	condition.setVersion(projectInfo.getVersion());
        	List<RuleGroup> ruleGroups = this.ruleGroupService.findList(condition);
        	RuleVersioninfo ruleVersion = this.ruleManageService.findRuleVersionInfo(rulemanage.getProjectCode(), rulemanage.getId());
        	if (ruleVersion != null) {
        		ruleEditEntity.setDatasetNames(ruleVersion.getDatasetNames());
        	}
        	ruleEditEntity.setRuleGroups(ruleGroups);
        	responseVO.setData(ruleEditEntity);
    	}catch(Exception e) {
    		e.printStackTrace();
    		responseVO.setStatus(ResponseVO.ERROR);
    		responseVO.setDescription(e.getMessage());
    	}
    	return responseVO;
    }
    /**
     * 获取规则详情
     *
     * @param scoreId 评分模型ID
     * @param version 评分模型版本号（若不传，取最新版）
     * @return 评分模型信息及规则信息
     */
    @RequestMapping(value = "getGeneralRule")
    public @ResponseBody
    JsonMessage getGeneralRule(HttpServletRequest request, String manageId, @RequestParam(value = "version") String version, String temp) throws Exception {
        JsonMessage ret = new JsonMessage();
        try {
        	RuleGroup ruleGroup = new RuleGroup();
        	ruleGroup.setProjectCode(getCurrProjectCode());
        	ruleGroup.setManageId(manageId);
        	ruleGroup.setVersion(version);
            List<RuleGroup> rgList = this.ruleGroupService.findList(ruleGroup);
            ret.setData(rgList.get(0));
        } catch (Exception e) {
            LoggerManager.error(e.getMessage(), e, this.getClass());
            ret.setResult(false);
            ret.setMessage("规则信息获取失败，请查看日志");
        }
        return ret;
    }
    /**
     * 保存规则到数据库中
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param map      ModelMap
     * @return 新增结果信息
     */
    @RequestMapping("saveOrUpdate")
    public ResponseVO saveOrUpdate(@RequestBody RuleEditEntity ruleEditEntity) throws Exception {
        ResponseVO res = new ResponseVO();
        res.setStatus(ResponseVO.OK);
        try {
            Integer num = this.ruleManageService.countListFindName(ruleEditEntity.getRuleManage(), ruleEditEntity.getRuleManage().getModelType());
            if (num != null && num>0) {
                res.setStatus(ResponseVO.ERROR);
                res.setDescription("变量名称重复，请使用其他有效名称");
                return res;
            }
            this.ruleGroupService.saveOrUpdateRule(ruleEditEntity);
        } catch (Exception e) {
            e.printStackTrace();
            res.setDescription(e.getMessage());
            res.setStatus(ResponseVO.ERROR);;
        }
        return res;
    }

    /**
     * 修改规则集
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param code     普通规则编码
     * @param type     规则集类别 普通，一般，政策
     * @param map      ModelMap
     * @param id       规则项ID
     * @return 修改结果信息
     */
    @RequestMapping("delRuleVo")
    public @ResponseBody
    ResMessage delRuleVo(ModelMap map, String id) throws Exception {
        if (StringUtils.isEmpty(id)) {
            throw new BizException("E-000600");
        }
        this.ruleGroupService.delGeneralRule(id);
        DataCache.ruleRefEntryGroupChange(this.getCurrProjectCode());//清理缓存
        return new ResMessage("success", "删除成功！");
    }

    /**
     * 通过转换器将页面配置转换成Drl文本 show rule item drl
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param map      ModelMap
     * @return Drl文本
     */
    @RequestMapping("showRuleItmeDrl")
    public @ResponseBody
    ResMessage showRuleItmeDrl(HttpServletRequest request, HttpServletResponse response, @RequestBody RuleSetVO ruleSetVO) throws Exception {
        ResMessage res = new ResMessage();
        String manageId = ruleSetVO.getRuleManage().getId();
        if (StringUtils.isEmpty(manageId)) {
            ruleSetVO.getRuleManage().setProjectCode(getCurrProjectCode());
            ruleSetVO.getRuleManage().setCode(this.ruleManageService.generalCodeByType(RuleModelTypeEnum.GeneralRule.code, this.getCurrProjectCode()));
            ruleSetVO.getRuleManage().setModelType(RuleModelTypeEnum.GeneralRule.code);
            ruleSetVO.getRuleManage().setVersion("v0.01");
        } else {
            ruleSetVO.setRuleManage(this.ruleManageService.get(manageId));

        }
        ruleSetVO.getRuleManage().setProjectCode(this.getCurrProjectCode());
        String drl = this.ruleGroupService.showRuleDrl(ruleSetVO);
        res.setCode("success");
        res.setMsg(drl);
        return res;
    }
    /**
     * 通过转换器将页面配置转换成java文本 show rule item java
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param map      ModelMap
     * @return Java文本
     */
    @RequestMapping("showJavaItmeRule")
    public @ResponseBody
    ResMessage showJavaItmeRule(HttpServletRequest request, HttpServletResponse response, @RequestBody RuleSetVO ruleSetVO) throws Exception {
        ResMessage res = new ResMessage();
        String manageId = ruleSetVO.getRuleManage().getId();
        if (StringUtils.isEmpty(manageId)) {
            ruleSetVO.getRuleManage().setProjectCode(getCurrProjectCode());
            ruleSetVO.getRuleManage().setCode(this.ruleManageService.generalCodeByType(RuleModelTypeEnum.GeneralRule.code, this.getCurrProjectCode()));
            ruleSetVO.getRuleManage().setModelType(RuleModelTypeEnum.GeneralRule.code);
            ruleSetVO.getRuleManage().setVersion("v0.01");
        } else {
            ruleSetVO.setRuleManage(this.ruleManageService.get(manageId));

        }
        ruleSetVO.getRuleManage().setProjectCode(this.getCurrProjectCode());
        String javacode = this.ruleGroupService.showRuleJava(ruleSetVO);
        res.setCode("success");
        res.setMsg(javacode);
        return res;
    }
    /**
     * 打开规则集 for 选择
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param code     普通规则编码
     * @param map      ModelMap
     * @return JSP路径
     */
    @RequestMapping("generalruleList")
    public String generalRuleListPage(HttpServletRequest request, HttpServletResponse response, String modelName, String code, ModelMap map) throws Exception {
        map.put("list", this.ruleGroupService.generalRuleList(this.getCurrProjectCode()));
        map.put("code", code);
        map.put("type", modelName);
        return "rule/generalrule/generalRuleList";
    }

    /**
     * 检查规则关联
     */
    @RequestMapping("checkRuleCorr")
    public @ResponseBody List<String> checkRuleCorr(String id) throws Exception {
    	List<String> nameList = new ArrayList<String>();
    	RuleGroupRef ruleGroupRef = new RuleGroupRef();
    	ruleGroupRef.setRuleId(id);
        List<RuleGroupRef> groupRefList = this.ruleGrouprefService.findList(ruleGroupRef);
        Map<String,String> manageId2Name = new HashMap<String,String>();
        for(RuleGroupRef groupRef:groupRefList) {
        	String manageId = groupRef.getManageId();
        	String ruleName = null;
        	if(manageId2Name.containsKey(manageId)) {
        		ruleName = manageId2Name.get(manageId);
        	}else {
        		RuleManage rm = this.ruleManageService.get(manageId);
        		ruleName = rm.getName();
        		manageId2Name.put(manageId, ruleName);
        	}
        	nameList.add(ruleName+"["+groupRef.getVersion()+"]");
        }
    	return nameList;
    }

    /**
     * 查询规则关联
     * @param id 指ruleGroup的manageId
     */
    @RequestMapping("ruleReference")
    public @ResponseBody RuleRefVOPage ruleReference(RuleRefVOPage ruleRefVOPage) throws Exception {
    	ruleRefVOPage.setProjectCode(this.getCurrProjectCode());
    	RuleRefVOPage page = ruleGroupService.findRuleReference(ruleRefVOPage);
    	return page;
    }

    /**
     * 复制规则 ljt 2019-12-20
     * @param id
     * @return
     */
    @RequestMapping("copyRule")
    public @ResponseBody ResponseVO copyRule(@RequestBody ProjectInfo  projectInfo){
    	ResponseVO res = new ResponseVO();
    	res.setStatus(ResponseVO.OK);
    	res.setDescription("复制成功");
        try{
            ruleGeneralService.copyRuleItem(projectInfo.getManageId());
        }catch (Exception e){
        	String error = ExceptionUtils.getStackTrace(e);
        	logger.error(error);
        	res.setStatus(ResponseVO.ERROR);
        	res.setDescription(e.getMessage());
        	res.setDesDetail(error);
        }
        return res;
    }
    /**
     * 编译规则 xch 2019-12-23
     * @param id
     * @return
     */
    @RequestMapping("compileRuleDrl")
    @ResponseBody
    public ResMessage compileRuleDrl(ModelMap map,@RequestBody RuleGroupInfo ruleGroupInfo){
    	 String meg = "";
         try {
        	 String[] ids = ruleGroupInfo.getFromGeneral();
        	 meg = this.ruleGeneralService.compileDrl(ids);
         } catch (Exception e) {
         	e.printStackTrace();
             return new ResMessage("fail", e.getMessage());
         }
         return new ResMessage("success", meg);
    }
    
    @RequestMapping("testRuleGroup")
    @ResponseBody
    public ResponseVO testRuleGroup(@RequestBody RuleExecuteVO  ruleExecuteVO) {
    	ResponseVO  resVo = new ResponseVO();
    	  String  projectCode  =null;
    	  try {
 			 projectCode= this.getCurrProjectCode();
			 String  dwFilePath = this.ruleGroupService.exportRuleExc(projectCode,ruleExecuteVO.getInputXml());
			 resVo.setData(dwFilePath);  
 		  } catch (Exception e) {
 			 LoggerManager.error("", e, this.getClass());
 			 Throwable root = ExceptionUtils.getRootCause(e);
 			 if( root == null ) {
 				 root = e;
 			 }
 			 resVo.setDescription("测试失败：" + root.getMessage());
             String desDetail = com.tansun.easycare.core.utils.StringUtils.toHtml(ExceptionUtils.getStackTrace(e));
             resVo.setDesDetail(desDetail);
			 resVo.setStatus(ResponseVO.ERROR);
		 }
    	 return  resVo; 
    }
    
    @SuppressWarnings("unchecked")
	@RequestMapping("getRuleDataModel")
    @ResponseBody
    public ResponseVO getRuleDataModel() {
    	ResponseVO  resVo = new ResponseVO();
    	try {
    		String  projectCode  = this.getCurrProjectCode();
    		Map<String, MClass> metaMap = dataBomService.findMapClass(projectCode);
    		JSONObject json = new JSONObject();
    		for(String className:metaMap.keySet()) {
    			MClass mClass = metaMap.get(className);
    			Map<String, MField> map = mClass.getFieldMap();
    			JSONObject child = new JSONObject();
    			json.put(className, child);
    			for(String name:map.keySet()) {
    				MField mField = map.get(name);
    				String dataType = mField.getType();
    				String defaultValue = mField.getDefaultValue();
    				String coll = mField.getCollection();
    				Object val = null;
    				if("Double".equals(dataType)) {
    					if(StringUtils.isEmpty(defaultValue)){
    						val = 0.0;
    					}else {
    						val = Double.parseDouble(defaultValue);
    					}
    				}else if("Long".equals(dataType)){
    					if(StringUtils.isEmpty(defaultValue)){
    						val = 0l;
    					}else {
    						val = Long.parseLong(defaultValue);
    					}
    				}else if("Boolean".equals(dataType)){
    					if(StringUtils.isEmpty(defaultValue)){
    						val = true;
    					}else {
    						val = Boolean.parseBoolean(defaultValue);
    					}
    				}else {
    					if(StringUtils.isEmpty(defaultValue)){
    						val = "";
    					}else {
    						val = defaultValue;
    					}
    				}
    				if("List".equals(coll)) {
    					List<Object> list = null;
    					if(child.containsKey(name)) {
    						list = (List<Object>)child.get(name);
    					}else {
    						list = new ArrayList<>();
    						child.put(name, list);
    					}
    					list.add(val);
    				}else {
    					child.put(name, val);
    				}
    			}
    		}
    		resVo.setData(json.toJSONString());
    		resVo.setStatus(ResponseVO.OK);
 		} catch (Exception e) {
			 e.printStackTrace();
			 resVo.setStatus(ResponseVO.ERROR);
		}
    	return  resVo; 
    }
    @RequestMapping("downRuleTest")
    @ResponseBody
    public  ResMessage  downRuleTest(String  filePath,HttpServletRequest req,HttpServletResponse res) {
  	  ResMessage  resMessage  = new ResMessage();
  	  try {
           File  file  = new  File(filePath);
           if (file.exists()) {
               OutputStream os = res.getOutputStream();
               res.reset();
               res.setContentType("application/octet-stream; charset=utf-8");
               String filename = "ruleRusult.xlsx";
               res.setHeader("Content-Disposition", "attachment; filename=" + filename);
               try {
                   os.write(FileUtils.readFileToByteArray(new File(filePath)));
                   os.flush();
               } catch (Exception e) {
                   LoggerManager.error("", e, this.getClass());
               } finally {
                   if (os != null) {
                       os.close();
                   }
               }
           }
           
		  } catch (Exception e) {
			 e.printStackTrace();
		 }
  	 return  resMessage; 
    }
    
    /**
     * 版本回退 xch 2019-01-07
     * @param id
     * @return
     */
    @RequestMapping("revertVersion")
    public  ResponseVO revertVersion(@RequestBody ProjectInfo projectInfo) throws Exception {
    	ResponseVO ret = new ResponseVO();
        try {
            RuleManage ruleManage = ruleManageService.get(projectInfo.getManageId());
            ruleManage.setVersion(projectInfo.getVersion());

            if (!StringUtils.isEmpty(projectInfo.getVersion())) {
            	ruleManage.setOldVersion(projectInfo.getVersion());
            	ruleManage.setStatus("1");
            } else {
            	ruleManage.setOldVersion(ruleManage.getVersion());
            	ruleManage.setStatus("2");
            }
            ruleManageService.saveOrUpdate(ruleManage);
            ruleGroupService.updateGeneralRuleVersion(ruleManage);
            //更新规则内容
            ruleVersioninfoService.updateRuleContent(ruleManage);
        } catch (Exception e) {
            LoggerManager.error(e.getMessage(), e, this.getClass());
            ret.setStatus(ResponseVO.ERROR);
            if (e instanceof ApplicationContextException) {
                ret.setDescription(e.getMessage());
            } else {
                ret.setDescription("回退失败，请查看日志");
            }
        }
        return ret;
    }
    
    @Override
    public void setRuleBizService() {
        super.setRuleBaseService(this.ruleGroupService);
    }
    
}
